package modelo;

import java.awt.Point;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;


public class ControladorJuego implements KeyObservator{
	
	private long intervaloSimulacion;
	private EstadosDelJuego estado;
	private CopyOnWriteArrayList<Contenido> objetosVivos;
	private CopyOnWriteArrayList<Dibujable> dibujables;
	private CopyOnWriteArrayList<KeyObservator> keyObservadores;
	private CopyOnWriteArrayList<Enemigo> enemigosADestruir;
	private Bombita jugador;
	private Mapa mapa;
	private Ventana superficieDeDibujo;	
	
	public ControladorJuego() throws IOException{
		this.intervaloSimulacion = 100; //default
		this.objetosVivos = new CopyOnWriteArrayList<Contenido>();
		this.dibujables = new CopyOnWriteArrayList<Dibujable>();
		this.keyObservadores = new CopyOnWriteArrayList<KeyObservator>();
		this.enemigosADestruir = new CopyOnWriteArrayList<Enemigo>();
		this.estado = EstadosDelJuego.Jugando;
		keyObservadores.add(this);

	}
	
	
	public void cargarMapa(Mapa mapa){
		this.mapa = mapa;
	}

	public void comenzar () {
		try{
			while(nivelEnJuego()) {
				if(!(this.estado == EstadosDelJuego.Pausado)) {
					simular();
				}

			}
			Thread.sleep(intervaloSimulacion);	
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public EstadosDelJuego actualizarEstado(){
		if((this.enemigosADestruir.size() == 0) && this.jugador.salidaEncontrada()){
			this.estado = EstadosDelJuego.Ganado;
			System.out.print("Juego ganado");
		}
		
		if(!jugador.estaVivo()){
			this.estado = EstadosDelJuego.Perdido;
			System.out.print("Juego perdido");
		}
		
		return this.estado;
	}
	
	
	public boolean nivelEnJuego(){		
		return !((this.actualizarEstado() == EstadosDelJuego.Ganado) || (this.actualizarEstado() == EstadosDelJuego.Perdido) );

	}
	
	
	public void agregarObjetoVivo(Contenido objetoVivo) {
		objetosVivos.add(objetoVivo);
	}
	
	
	public void pausar_despausar(){
		if (estado == EstadosDelJuego.Pausado) estado = EstadosDelJuego.Jugando;
		else estado = EstadosDelJuego.Pausado;
	}
	
	public void agregarDibujable(Dibujable unDibujable) {
		dibujables.add(unDibujable);
	}
	
	public void agregarEnemigo(Enemigo enemigo){
		enemigosADestruir.add(enemigo);
	}
	
	
	public long getIntervaloSimulacion() {
		return intervaloSimulacion;
	}

	public void setIntervaloSimulacion(long intervaloSimulacion) {
		this.intervaloSimulacion = intervaloSimulacion;
	}

	private void dibujar() {
		Iterator<Dibujable> iterador = dibujables.iterator();
		while(iterador.hasNext()){
			Dibujable dibujable = (Dibujable)iterador.next();
			dibujable.dibujar(this.superficieDeDibujo);
		}
		this.superficieDeDibujo.actualizar();
	}
	
	private void simular() throws IOException{
		this.superficieDeDibujo.limpiar();
		Iterator<Contenido> iterador = objetosVivos.iterator();
		while(iterador.hasNext()){
			((Contenido)iterador.next()).vivir(mapa, objetosVivos);
			this.agregarVistaArma();
			
			this.limpiarNoVivos();
			if (!this.nivelEnJuego()){
				break;
			}
			
			dibujar();
			
			try{
				Thread.sleep(intervaloSimulacion);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
	
	public void limpiarNoVivos(){
		Iterator<Contenido> iterador = this.objetosVivos.iterator();
		System.out.print("Actualizar objetos vivos\n");
		
		while (iterador.hasNext()){
			Contenido objeto = iterador.next();
			if(!objeto.estaVivo()){
				this.objetosVivos.remove(objeto);
				this.enemigosADestruir.remove(objeto);
				this.eliminarVista(objeto);
				this.mapa.quitarContenido(objeto);	
				System.out.print("objeto no vivo"+objeto.getClass()+"\n");
			}
		}
		
		System.out.print(this.objetosVivos.size() + " objetos vivos\n");
		
	}
	

	public SuperficieDeDibujo getSuperficieDeDibujo() {
		return superficieDeDibujo;
	}

	public void setSuperficieDeDibujo(Ventana superficieDeDibujo) {
		this.superficieDeDibujo = superficieDeDibujo;
	}
	

	
	public void despacharKey(int keyCode) {
		KeyObservator unKeyObservador;
		Iterator<KeyObservator> iterador = this.keyObservadores.iterator();
		while(iterador.hasNext()){
			unKeyObservador = (KeyObservator) iterador.next();
			unKeyObservador.keyTyped(keyCode);
		}
	}
		
	

	public void agregarKeyObservador(KeyObservator unKeyObservador) {
		this.keyObservadores.add(unKeyObservador);
	}
	
	

	public void keyTyped (int keyCode) {

		if(keyCode==KeyEvent.VK_P)
			this.pausar_despausar();
	
	}

	
	public CopyOnWriteArrayList<Contenido> getObjetosVivos(){
		return this.objetosVivos;
	}
	
	
	public void ubicarContenidos(){
		
		Random rnd = new Random();
		rnd.setSeed(new Date().getTime());
		ListIterator<Contenido> it = this.objetosVivos.listIterator();
		
		while (it.hasNext()){
			
			Contenido contenido = it.next();
			Point posicion = new Point(rnd.nextInt(this.mapa.getFilas()), rnd.nextInt(this.mapa.getColumnas()));
			Casillero cas = this.mapa.obtenerCasillero(posicion);
		
			while (!contenido.casilleroValido(cas)){
				posicion = new Point(rnd.nextInt(this.mapa.getFilas()), rnd.nextInt(this.mapa.getColumnas()));
				cas = this.mapa.obtenerCasillero(posicion);
			}
			
			System.out.print("Posicion: (" + posicion.getX() + "," + posicion.getY() + ") = " + contenido.toString() + "\n");
		
			cas.agregarContenido(contenido);
		}
		
		System.out.print("Ubicacion de contenidos\n");
		
	}
	
	public void eliminarVista(Contenido objeto){
		
		Iterator<Dibujable> iterador = this.dibujables.iterator();
		
		while (iterador.hasNext()){
			Dibujable vista = iterador.next();
			if((vista.getPosicionable()) == objeto){
				this.dibujables.remove(vista);

			}
		}
		
	}
	
	public void setJugador(Bombita bombita){
		this.jugador = bombita;
	}
	
	public void agregarVistaArma() throws IOException{
		Iterator<Contenido> iterador = this.objetosVivos.iterator();
		
		while(iterador.hasNext()){
			Contenido objeto = iterador.next();
			Imagen vistaArma = null;
			if (objeto.getClass() == Misil.class)
				vistaArma = new Imagen(this.getClass().getResource("/MISIL.png"),objeto,30);
			
			else if ((objeto.getClass() == BombaMolotov.class) || (objeto.getClass() == BombaToletole.class))
				vistaArma = new Imagen(this.getClass().getResource("/BOMBA.png"),objeto,30);
			
			if (!(vistaArma == null) && !(dibujables.contains(vistaArma)))
					dibujables.add(vistaArma);
		}
	}
}



